package utils

import "sync"

type SpiritMap struct {
	Lock *sync.RWMutex
	Map  map[string]interface{}
}

func NewSpiritMap() *SpiritMap {
	return &SpiritMap{
		Lock: new(sync.RWMutex),
		Map:  make(map[string]interface{}),
	}
}

func (m *SpiritMap) Get(k string) interface{} {
	m.Lock.RLock()
	defer m.Lock.RUnlock()
	if val, ok := m.Map[k]; ok {
		return val
	}
	return nil
}

// Maps the given key and value. Returns false
// if the key is already in the map and changes nothing.
func (m *SpiritMap) Set(k string, v interface{}) bool {
	m.Lock.Lock()
	defer m.Lock.Unlock()
	if val, ok := m.Map[k]; !ok {
		m.Map[k] = v
	} else if val != v {
		m.Map[k] = v
	} else {
		return false
	}
	return true
}

// Returns true if k is exist in the map.
func (m *SpiritMap) Check(k string) bool {
	m.Lock.RLock()
	defer m.Lock.RUnlock()
	if _, ok := m.Map[k]; !ok {
		return false
	}
	return true
}

func (m *SpiritMap) Delete(k string) {
	m.Lock.Lock()
	defer m.Lock.Unlock()
	delete(m.Map, k)
}
